package org.lisy.java.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 文件流操作
 * 
 * @author lisy
 */
public class FileStreamOperate {

	// 目标文件目录
	private final static String TARGET_IO_FILE_DIR = "./deploy/target/io";
	
	/**
	 * Bit 最小的二进制单位 ，是计算机的操作部分。取值 0 或者 1
	 * Byte（字节）是计算机操作数据的最小单位由 8 位 bit 组成 取值（-128-127）
	 * Char（字符）是用户的可读写的最小单位，在 Java 里面由 16 位 bit 组成 取值（0-65535）
	 * 字节流: 操作 byte 类型数据，主要操作类是 OutputStream、InputStream 的子类；不用缓冲区，直接对文件本身操作
	 * 字符流: 操作字符类型数据，主要操作类是 Reader、Writer 的子类；使用缓冲区缓冲字符， 不关闭流就不会输出任何内容
	 * 互相转换: 
	 *   OutputStreamWriter：是 Writer 的子类，将输出的字符流变为字节流，即将一个字符流的输出对象变为字节流输出对象
	 *   InputStreamReader：是 Reader 的子类，将输入的字节流变为字符流，即将一个字节流的输入对象变为字符流的输入对象
	 */
	public static void main(String[] args) {
		
		int count = 100000;
		
		// 字符流，生成文件
		fileWriteFile(count);
		
		// 字节流，生成文件
		fileOutputStreamFile(count);
		
		// 字节流，使用缓冲流生成文件
		bufferedOutputStreamFile(count);
		
		// 字符流，读取文件
		fileReaderFile();
		
		// 字节流，使用缓冲流读取文件
		bufferedInputStream();
	}

	private static void fileWriteFile(int count) {
		FileWriter fileWriter = null;
		try {
			String filePath = TARGET_IO_FILE_DIR + File.separator + "file_writer.txt";
			File file = new File(filePath);
			if (!file.exists()) {
				// 如果上级不存在，就会自动创建
				file.getParentFile().mkdirs();
			} else {
				file.delete();
			}
			fileWriter = new FileWriter(filePath);
			long begin = System.currentTimeMillis();
			for (int i = 0; i < count; i++) {
				fileWriter.write("测试 java 文件操作\r\n");
			}
			fileWriter.close();
			long end = System.currentTimeMillis();
			System.out.println("FileWriter consume:" + (end - begin) + " ms");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fileWriter != null) {
				try {
					fileWriter.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static void fileOutputStreamFile(int count) {
		FileOutputStream fileOutputStream = null;
		try {
			String filePath = TARGET_IO_FILE_DIR + File.separator + "file_output_stream.txt";
			File file = new File(filePath);
			if (!file.exists()) {
				// 如果上级不存在，就会自动创建
				file.getParentFile().mkdirs();
			} else {
				file.delete();
			}
			fileOutputStream = new FileOutputStream(file);
			long begin = System.currentTimeMillis();
			for (int i = 0; i < count; i++) {
				fileOutputStream.write("测试 java 文件操作\r\n".getBytes());
			}
			fileOutputStream.close();
			long end = System.currentTimeMillis();
			System.out.println("FileOutputStream consume:" + (end - begin) + " ms");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fileOutputStream != null) {
				try {
					fileOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static void bufferedOutputStreamFile(int count) {
		FileOutputStream fileOutputStream = null;
		BufferedOutputStream bufferedOutputStream = null;
		try {
			String filePath = TARGET_IO_FILE_DIR + File.separator + "buffered_output_stream.txt";
			File file = new File(filePath);
			if (!file.exists()) {
				// 如果上级不存在，就会自动创建
				file.getParentFile().mkdirs();
			} else {
				file.delete();
			}
			fileOutputStream = new FileOutputStream(file);
			bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
			long begin = System.currentTimeMillis();
			for (int i = 0; i < count; i++) {
				bufferedOutputStream.write("测试 java 文件操作\r\n".getBytes());
			}
			bufferedOutputStream.flush();
			bufferedOutputStream.close();
			fileOutputStream.close();
			long end = System.currentTimeMillis();
			System.out.println("BufferedOutputStream consume:" + (end - begin) + " ms");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bufferedOutputStream != null) {
				try {
					bufferedOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fileOutputStream != null) {
				try {
					fileOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static void fileReaderFile() {
		FileReader fileReader = null;
		try {
			String filePath = TARGET_IO_FILE_DIR + File.separator + "file_writer.txt";
			fileReader = new FileReader(filePath);
			int readNum = 0;
			int readcount = 0;
			// read() 每次读取一个字符， 可以使用数组，为-1时表示没有数据
			char[] buf = new char[1024];
			int length = 0;
			long begin = System.currentTimeMillis();
			while ((length = fileReader.read(buf)) != -1) {
				readNum++; // 循环次数
				readcount += length; // 读取到的字符数
			}
			long end = System.currentTimeMillis();
			System.out.println("FileReader num: " + readNum + " length: " + readcount);
			System.out.println("FileReader consume:" + (end - begin) + " ms");
			fileReader.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fileReader != null) {
				try {
					fileReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static void bufferedInputStream() {
		FileInputStream inputStream = null;
		BufferedInputStream bufferedInputStream = null;
		try {
			String filePath = TARGET_IO_FILE_DIR + File.separator + "buffered_output_stream.txt";
			inputStream = new FileInputStream(filePath);
			bufferedInputStream = new BufferedInputStream(inputStream);
			int readNum = 0;
			int readcount = 0;
			// read() 一次只读一个字节， 可以使用数组，为-1时表示没有数据
			byte[] bytes = new byte[1024];
			int length = 0;
			long begin = System.currentTimeMillis();
			while ((length = bufferedInputStream.read(bytes)) != -1) {
				readNum++; // 循环次数
				readcount += length; // 读取到的字节数
			}
			long end = System.currentTimeMillis();
			System.out.println("BufferedInputStream num: " + readNum + " length: " + readcount);
			System.out.println("BufferedInputStream consume:" + (end - begin) + " ms");
			bufferedInputStream.close();
			inputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bufferedInputStream != null) {
				try {
					bufferedInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
